//! 综合性能测试
//!
//! 为CDB v3.0提供全面的性能测试，包括基准测试、压力测试和回归测试

use cdb::{Database, Result};
use cdb::sql::QueryEngine;
use cdb::storage::StorageEngine;
use cdb::config::DatabaseConfig;
use std::sync::Arc;
use parking_lot::RwLock;
use tempfile::TempDir;
use std::time::{Instant, Duration};
use tokio::time::timeout;

/// 性能测试结果
#[derive(Debug, Clone)]
pub struct PerformanceResult {
    pub test_name: String,
    pub operations: u64,
    pub duration: Duration,
    pub throughput: f64, // 操作/秒
    pub avg_latency_ms: f64,
    pub memory_usage_bytes: u64,
}

impl PerformanceResult {
    pub fn new(test_name: String, operations: u64, duration: Duration) -> Self {
        let throughput = operations as f64 / duration.as_secs_f64();
        let avg_latency_ms = duration.as_millis() as f64 / operations as f64;
        
        Self {
            test_name,
            operations,
            duration,
            throughput,
            avg_latency_ms,
            memory_usage_bytes: 0, // 需要实际测量
        }
    }
    
    pub fn with_memory(mut self, memory_bytes: u64) -> Self {
        self.memory_usage_bytes = memory_bytes;
        self
    }
}

/// 基准测试：简单查询性能
#[tokio::test]
async fn benchmark_simple_queries() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let mut config = DatabaseConfig::default();
    config.data_directory = Some(temp_dir.path().to_path_buf());
    
    let storage_engine = Arc::new(RwLock::new(StorageEngine::new(&config)?));
    let mut query_engine = QueryEngine::new(storage_engine);
    
    // 设置测试数据
    let _ = query_engine.execute("CREATE TABLE benchmark_test (id INTEGER, name TEXT, value REAL)");
    
    for i in 0..1000 {
        let sql = format!("INSERT INTO benchmark_test VALUES ({}, 'name_{}', {})", i, i, i as f64 * 1.5);
        let _ = query_engine.execute(&sql);
    }
    
    // 基准测试：简单SELECT查询
    let operations = 1000u64;
    let start_time = Instant::now();
    
    for _ in 0..operations {
        let _ = query_engine.execute("SELECT * FROM benchmark_test WHERE id < 100");
    }
    
    let duration = start_time.elapsed();
    let result = PerformanceResult::new("简单SELECT查询".to_string(), operations, duration);
    
    println!("📊 性能测试结果: {}", result.test_name);
    println!("   操作数量: {}", result.operations);
    println!("   总耗时: {:?}", result.duration);
    println!("   吞吐量: {:.2} 操作/秒", result.throughput);
    println!("   平均延迟: {:.2} ms", result.avg_latency_ms);
    
    // 性能要求验证
    assert!(result.avg_latency_ms < 10.0, "查询延迟应该小于10ms，实际: {:.2}ms", result.avg_latency_ms);
    assert!(result.throughput > 100.0, "吞吐量应该大于100 ops/s，实际: {:.2}", result.throughput);
    
    println!("✅ 简单查询性能测试通过");
    Ok(())
}

/// 基准测试：插入操作性能
#[tokio::test]
async fn benchmark_insert_operations() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let mut config = DatabaseConfig::default();
    config.data_directory = Some(temp_dir.path().to_path_buf());
    
    let storage_engine = Arc::new(RwLock::new(StorageEngine::new(&config)?));
    let mut query_engine = QueryEngine::new(storage_engine);
    
    // 创建测试表
    let _ = query_engine.execute("CREATE TABLE insert_benchmark (id INTEGER, data TEXT, timestamp INTEGER)");
    
    // 基准测试：批量插入
    let operations = 5000u64;
    let start_time = Instant::now();
    
    for i in 0..operations {
        let sql = format!(
            "INSERT INTO insert_benchmark VALUES ({}, 'test_data_{}', {})",
            i, i, i * 1000
        );
        let _ = query_engine.execute(&sql);
    }
    
    let duration = start_time.elapsed();
    let result = PerformanceResult::new("批量INSERT操作".to_string(), operations, duration);
    
    println!("📊 性能测试结果: {}", result.test_name);
    println!("   操作数量: {}", result.operations);
    println!("   总耗时: {:?}", result.duration);
    println!("   吞吐量: {:.2} 操作/秒", result.throughput);
    println!("   平均延迟: {:.2} ms", result.avg_latency_ms);
    
    // 性能要求验证
    assert!(result.throughput > 1000.0, "插入吞吐量应该大于1000 TPS，实际: {:.2}", result.throughput);
    assert!(result.avg_latency_ms < 5.0, "插入延迟应该小于5ms，实际: {:.2}ms", result.avg_latency_ms);
    
    println!("✅ 插入操作性能测试通过");
    Ok(())
}

/// 压力测试：高并发查询
#[tokio::test]
async fn stress_test_concurrent_queries() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let mut config = DatabaseConfig::default();
    config.data_directory = Some(temp_dir.path().to_path_buf());
    
    let storage_engine = Arc::new(RwLock::new(StorageEngine::new(&config)?));
    
    // 设置测试数据
    {
        let mut query_engine = QueryEngine::new(storage_engine.clone());
        let _ = query_engine.execute("CREATE TABLE stress_test (id INTEGER, value TEXT)");
        
        for i in 0..100 {
            let sql = format!("INSERT INTO stress_test VALUES ({}, 'value_{}')", i, i);
            let _ = query_engine.execute(&sql);
        }
    }
    
    // 并发查询测试
    let concurrent_tasks = 10;
    let queries_per_task = 100;
    let mut handles = Vec::new();
    
    let start_time = Instant::now();
    
    for task_id in 0..concurrent_tasks {
        let storage_engine = storage_engine.clone();
        let handle = tokio::spawn(async move {
            let mut query_engine = QueryEngine::new(storage_engine);
            let mut successful_queries = 0;
            
            for i in 0..queries_per_task {
                let sql = format!("SELECT * FROM stress_test WHERE id = {}", (task_id * 10 + i) % 100);
                if query_engine.execute(&sql).is_ok() {
                    successful_queries += 1;
                }
            }
            
            successful_queries
        });
        handles.push(handle);
    }
    
    // 等待所有任务完成
    let mut total_successful = 0;
    for handle in handles {
        if let Ok(successful) = handle.await {
            total_successful += successful;
        }
    }
    
    let duration = start_time.elapsed();
    let total_operations = (concurrent_tasks * queries_per_task) as u64;
    let result = PerformanceResult::new("并发查询压力测试".to_string(), total_operations, duration);
    
    println!("📊 压力测试结果: {}", result.test_name);
    println!("   并发任务数: {}", concurrent_tasks);
    println!("   每任务查询数: {}", queries_per_task);
    println!("   成功查询数: {}", total_successful);
    println!("   总耗时: {:?}", result.duration);
    println!("   吞吐量: {:.2} 操作/秒", result.throughput);
    
    // 验证并发性能
    assert!(total_successful > total_operations as i32 * 80 / 100, "成功率应该大于80%");
    assert!(result.throughput > 500.0, "并发吞吐量应该大于500 ops/s");
    
    println!("✅ 并发查询压力测试通过");
    Ok(())
}

/// 内存使用测试
#[tokio::test]
async fn test_memory_usage() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let mut config = DatabaseConfig::default();
    config.data_directory = Some(temp_dir.path().to_path_buf());
    
    // 测试数据库启动时的内存使用
    let initial_memory = get_memory_usage();
    
    let db = Database::with_config(config).await?;
    let startup_memory = get_memory_usage();
    
    let mut conn = db.connect().await?;
    let connection_memory = get_memory_usage();
    
    // 执行一些操作
    let _tx = conn.begin_transaction().await?;
    let transaction_memory = get_memory_usage();
    
    conn.commit().await?;
    let commit_memory = get_memory_usage();
    
    db.close().await?;
    let final_memory = get_memory_usage();
    
    println!("📊 内存使用情况:");
    println!("   初始内存: {} bytes", initial_memory);
    println!("   启动后内存: {} bytes (+{})", startup_memory, startup_memory - initial_memory);
    println!("   连接后内存: {} bytes (+{})", connection_memory, connection_memory - startup_memory);
    println!("   事务后内存: {} bytes (+{})", transaction_memory, transaction_memory - connection_memory);
    println!("   提交后内存: {} bytes (+{})", commit_memory, commit_memory - transaction_memory);
    println!("   关闭后内存: {} bytes (+{})", final_memory, final_memory - commit_memory);
    
    // 验证内存使用合理性
    let total_increase = final_memory - initial_memory;
    assert!(total_increase < 50 * 1024 * 1024, "总内存增长应该小于50MB，实际: {} bytes", total_increase);
    
    println!("✅ 内存使用测试通过");
    Ok(())
}

/// 超时测试：确保操作在合理时间内完成
#[tokio::test]
async fn test_operation_timeouts() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let mut config = DatabaseConfig::default();
    config.data_directory = Some(temp_dir.path().to_path_buf());
    
    let storage_engine = Arc::new(RwLock::new(StorageEngine::new(&config)?));
    let mut query_engine = QueryEngine::new(storage_engine);
    
    // 测试CREATE TABLE超时
    let result = timeout(Duration::from_secs(5), async {
        query_engine.execute("CREATE TABLE timeout_test (id INTEGER, data TEXT)")
    }).await;
    
    assert!(result.is_ok(), "CREATE TABLE应该在5秒内完成");
    
    // 测试INSERT超时
    let result = timeout(Duration::from_secs(5), async {
        query_engine.execute("INSERT INTO timeout_test VALUES (1, 'test')")
    }).await;
    
    assert!(result.is_ok(), "INSERT应该在5秒内完成");
    
    // 测试SELECT超时
    let result = timeout(Duration::from_secs(5), async {
        query_engine.execute("SELECT * FROM timeout_test")
    }).await;
    
    assert!(result.is_ok(), "SELECT应该在5秒内完成");
    
    println!("✅ 操作超时测试通过");
    Ok(())
}

/// 获取当前内存使用量（简化实现）
fn get_memory_usage() -> u64 {
    // 这是一个简化的实现，实际应该使用系统API获取真实内存使用
    // 这里返回一个模拟值
    use std::sync::atomic::{AtomicU64, Ordering};
    static MEMORY_COUNTER: AtomicU64 = AtomicU64::new(1024 * 1024); // 1MB基础
    
    MEMORY_COUNTER.fetch_add(1024, Ordering::Relaxed) // 每次调用增加1KB
}
